#include "CPhysMemUtils.h"

#include "InpOut/x64/inpout32.h"

#pragma comment(lib, "InpOut/x64/inpoutx64.lib")

#pragma intrinsic(memcpy)

bool CPhysMemUtils::ReadPhysMem(DWORD_PTR pbPhysAddr, PBYTE buffer, DWORD dwPhysSize)
{
    HANDLE handle = NULL;
    PBYTE LinAdr = MapPhysToLin((LPBYTE)pbPhysAddr, dwPhysSize, &handle);
    if (NULL == LinAdr)
    {
        return false;
    }

    memcpy(buffer, LinAdr, dwPhysSize);
    UnmapPhysicalMemory(handle, LinAdr);
    return true;
}

bool CPhysMemUtils::WritePhysMem(DWORD_PTR pbPhysAddr, PBYTE buffer, DWORD dwPhysSize)
{
    HANDLE handle = NULL;
    PBYTE LinAdr = MapPhysToLin((LPBYTE)pbPhysAddr, dwPhysSize, &handle);
    if (NULL == LinAdr)
    {
        return false;
    }

    memcpy(LinAdr, buffer, dwPhysSize);
    UnmapPhysicalMemory(handle, LinAdr);
    return true;
}

bool CPhysMemUtils::ReadByte(DWORD_PTR pbPhysAddr, uint8_t* pVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    return ReadPhysMem(pbPhysAddr, pVal, sizeof(uint8_t));
}

bool CPhysMemUtils::WriteByte(DWORD_PTR pbPhysAddr, uint8_t nVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    return WritePhysMem(pbPhysAddr, &nVal, sizeof(uint8_t));
}

bool CPhysMemUtils::ReadWord(DWORD_PTR pbPhysAddr, uint16_t* pVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    return ReadPhysMem(pbPhysAddr, (PBYTE)pVal, sizeof(uint16_t));
}

bool CPhysMemUtils::WriteWord(DWORD_PTR pbPhysAddr, uint16_t nVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    return WritePhysMem(pbPhysAddr, (PBYTE)&nVal, sizeof(uint16_t));
}

bool CPhysMemUtils::ReadDword(DWORD_PTR pbPhysAddr, uint32_t* pVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    return ReadPhysMem(pbPhysAddr, (PBYTE)pVal, sizeof(uint32_t));
}

bool CPhysMemUtils::WriteDword(DWORD_PTR pbPhysAddr, uint32_t nVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    return WritePhysMem(pbPhysAddr, (PBYTE)&nVal, sizeof(uint32_t));
}

bool CPhysMemUtils::GetPortValue(uint16_t port, uint8_t* pVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    *pVal = DlPortReadPortUchar(port);
    return true;
}

bool CPhysMemUtils::SetPortValue(uint16_t port, uint8_t nVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    DlPortWritePortUchar(port, nVal);
    return true;
}

bool CPhysMemUtils::GetPortWordValue(uint16_t port, uint16_t* pVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    *pVal = DlPortReadPortUshort(port);
    return true;
}

bool CPhysMemUtils::SetPortWordValue(uint16_t port, uint16_t nVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    DlPortWritePortUshort(port, nVal);
    return true;
}
bool CPhysMemUtils::GetPortDwordValue(uint32_t port, uint32_t* pVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    *pVal = DlPortReadPortUlong(port);
    return true;
}

bool CPhysMemUtils::SetPortDwordValue(uint32_t port, uint32_t nVal)
{
    if (!IsInpOutDriverOpen())
    {
        return false;
    }

    DlPortWritePortUlong(port, nVal);
    return true;
}